<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 6.3.0">


  <link rel="apple-touch-icon" sizes="180x180" href="/myblog/images/apple-touch-icon.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/myblog/images/favicon-32x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/myblog/images/favicon-16x16.png">
  <link rel="mask-icon" href="/myblog/images/logo.svg" color="#222">

<link rel="stylesheet" href="/myblog/css/main.css">

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Monda:300,300italic,400,400italic,700,700italic%7CRoboto+Slab:300,300italic,400,400italic,700,700italic%7CNoto+Serif+SC:300,300italic,400,400italic,700,700italic%7CAmita:300,300italic,400,400italic,700,700italic%7CMontserrat:300,300italic,400,400italic,700,700italic%7CPT+Mono:300,300italic,400,400italic,700,700italic&display=swap&subset=latin,latin-ext">

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" integrity="sha256-AbA177XfpSnFEvgpYu1jMygiLabzPCJCRIBtR5jGc0k=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">

<script class="next-config" data-name="main" type="application/json">{"hostname":"wang-chen1119.gitee.io","root":"/myblog/","images":"/myblog/images","scheme":"Pisces","darkmode":false,"version":"8.13.1","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":{"enable":false,"style":null},"bookmark":{"enable":true,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"}}</script><script src="/myblog/js/config.js"></script>

    <meta name="description" content="第一章 并发编程的挑战上下文切换CPU通过为每个线程分配CPU时间片来支持支持单核处理器执行多线程代码。时间片非常短，CPU通过不断切换线程，让我们认为多个线程是同时执行的。 上下文切换 ：当线程执行完一个时间片后切换线程占有CPU，这是需要保存当前的执行状态，让再次切换到此线程时加载保存的执行状态继续执行。 如何减少上下文切换">
<meta property="og:type" content="blog">
<meta property="og:title" content="Java并发编程的艺术读书笔记">
<meta property="og:url" content="http://wang-chen1119.gitee.io/myblog/2022/10/29/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/index.html">
<meta property="og:site_name" content="Yorn&#39;s Notes">
<meta property="og:description" content="第一章 并发编程的挑战上下文切换CPU通过为每个线程分配CPU时间片来支持支持单核处理器执行多线程代码。时间片非常短，CPU通过不断切换线程，让我们认为多个线程是同时执行的。 上下文切换 ：当线程执行完一个时间片后切换线程占有CPU，这是需要保存当前的执行状态，让再次切换到此线程时加载保存的执行状态继续执行。 如何减少上下文切换">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://image-1305623006.cos.ap-nanjing.myqcloud.com/synchronized-get-lock-code-block.f8021972.png">
<meta property="og:image" content="https://image-1305623006.cos.ap-nanjing.myqcloud.com/synchronized-release-lock-block.c8310368.png">
<meta property="og:image" content="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220219162330599.png">
<meta property="og:image" content="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220220151156707.png">
<meta property="og:image" content="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220220151853914.png">
<meta property="og:image" content="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220220152417487.png">
<meta property="og:image" content="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220222194052103.png">
<meta property="og:image" content="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220222201040273.png">
<meta property="og:image" content="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220226105010740.png">
<meta property="og:image" content="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220226112938315.png">
<meta property="og:image" content="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220227132915283.png">
<meta property="og:image" content="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220227133437241.png">
<meta property="og:image" content="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220227134154343.png">
<meta property="og:image" content="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220227135146782.png">
<meta property="article:published_time" content="2022-10-29T05:32:16.064Z">
<meta property="article:modified_time" content="2022-10-29T05:31:55.760Z">
<meta property="article:author" content="yorn">
<meta property="article:tag" content="并发">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://image-1305623006.cos.ap-nanjing.myqcloud.com/synchronized-get-lock-code-block.f8021972.png">


<link rel="canonical" href="http://wang-chen1119.gitee.io/myblog/2022/10/29/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"http://wang-chen1119.gitee.io/myblog/2022/10/29/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/","path":"2022/10/29/并发编程/","title":"Java并发编程的艺术读书笔记"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>Java并发编程的艺术读书笔记 | Yorn's Notes</title>
  






  <noscript>
    <link rel="stylesheet" href="/myblog/css/noscript.css">
  </noscript>
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/myblog/" class="brand" rel="start">
      <i class="logo-line"></i>
      <p class="site-title">Yorn's Notes</p>
      <i class="logo-line"></i>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu"><li class="menu-item menu-item-首页"><a href="/myblog/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a></li><li class="menu-item menu-item-关于"><a href="/myblog/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a></li><li class="menu-item menu-item-标签"><a href="/myblog/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a></li><li class="menu-item menu-item-分类"><a href="/myblog/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a></li>
  </ul>
</nav>




</div>
        
  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>

  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%AC%AC%E4%B8%80%E7%AB%A0-%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E7%9A%84%E6%8C%91%E6%88%98"><span class="nav-number">1.</span> <span class="nav-text">第一章 并发编程的挑战</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%B8%8A%E4%B8%8B%E6%96%87%E5%88%87%E6%8D%A2"><span class="nav-number">1.1.</span> <span class="nav-text">上下文切换</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%A6%82%E4%BD%95%E5%87%8F%E5%B0%91%E4%B8%8A%E4%B8%8B%E6%96%87%E5%88%87%E6%8D%A2"><span class="nav-number">1.2.</span> <span class="nav-text">如何减少上下文切换</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%AD%BB%E9%94%81"><span class="nav-number">1.3.</span> <span class="nav-text">死锁</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%AC%AC%E4%BA%8C%E7%AB%A0Java%E5%B9%B6%E5%8F%91%E6%9C%BA%E5%88%B6%E7%9A%84%E5%BA%95%E5%B1%82%E5%AE%9E%E7%8E%B0"><span class="nav-number">2.</span> <span class="nav-text">第二章Java并发机制的底层实现</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#volatile%E7%9A%84%E5%BA%94%E7%94%A8"><span class="nav-number">2.1.</span> <span class="nav-text">volatile的应用</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#volatile%E7%9A%84%E5%AE%9A%E4%B9%89%E5%92%8C%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86"><span class="nav-number">2.1.1.</span> <span class="nav-text">volatile的定义和实现原理</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#volatile%E5%A6%82%E4%BD%95%E4%BF%9D%E8%AF%81%E5%8F%AF%E8%A7%81%E6%80%A7"><span class="nav-number">2.1.1.1.</span> <span class="nav-text">volatile如何保证可见性</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#synchronized%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86%E5%92%8C%E5%BA%94%E7%94%A8"><span class="nav-number">2.2.</span> <span class="nav-text">synchronized的实现原理和应用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8E%9F%E5%AD%90%E6%93%8D%E4%BD%9C%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86"><span class="nav-number">2.3.</span> <span class="nav-text">原子操作的实现原理</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9C%AF%E8%AF%AD%E5%AE%9A%E4%B9%89"><span class="nav-number">2.3.1.</span> <span class="nav-text">术语定义</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E5%8E%9F%E5%AD%90%E6%93%8D%E4%BD%9C"><span class="nav-number">2.3.2.</span> <span class="nav-text">如何实现原子操作</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Java%E5%AE%9E%E7%8E%B0%E5%8E%9F%E5%AD%90%E6%93%8D%E4%BD%9C"><span class="nav-number">2.3.3.</span> <span class="nav-text">Java实现原子操作</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%AC%AC%E4%B8%89%E7%AB%A0Java%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B"><span class="nav-number">3.</span> <span class="nav-text">第三章Java内存模型</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Java%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B%E7%9A%84%E5%9F%BA%E7%A1%80"><span class="nav-number">3.1.</span> <span class="nav-text">Java内存模型的基础</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E6%A8%A1%E5%9E%8B%E7%9A%84%E4%B8%A4%E4%B8%AA%E5%85%B3%E9%94%AE%E9%97%AE%E9%A2%98"><span class="nav-number">3.1.1.</span> <span class="nav-text">并发编程模型的两个关键问题</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Java%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B%E7%9A%84%E6%8A%BD%E8%B1%A1%E7%BB%93%E6%9E%84"><span class="nav-number">3.1.2.</span> <span class="nav-text">Java内存模型的抽象结构</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BB%8E%E6%BA%90%E4%BB%A3%E7%A0%81%E5%88%B0%E6%8C%87%E4%BB%A4%E5%BA%8F%E5%88%97%E7%9A%84%E9%87%8D%E6%8E%92%E5%BA%8F"><span class="nav-number">3.1.3.</span> <span class="nav-text">从源代码到指令序列的重排序</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%86%85%E5%AD%98%E5%B1%8F%E9%9A%9C%E7%B1%BB%E5%9E%8B"><span class="nav-number">3.1.4.</span> <span class="nav-text">内存屏障类型</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%87%8D%E6%8E%92%E5%BA%8F"><span class="nav-number">3.2.</span> <span class="nav-text">重排序</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%95%B0%E6%8D%AE%E4%BE%9D%E8%B5%96%E6%80%A7"><span class="nav-number">3.2.1.</span> <span class="nav-text">数据依赖性</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#as-if-serial"><span class="nav-number">3.2.2.</span> <span class="nav-text">as-if-serial</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%87%8D%E6%8E%92%E5%BA%8F%E5%AF%B9%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%BD%B1%E5%93%8D"><span class="nav-number">3.2.3.</span> <span class="nav-text">重排序对多线程的影响</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%A1%BA%E5%BA%8F%E4%B8%80%E8%87%B4%E6%80%A7"><span class="nav-number">3.3.</span> <span class="nav-text">顺序一致性</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%95%B0%E6%8D%AE%E7%AB%9E%E4%BA%89%E5%92%8C%E9%A1%BA%E5%BA%8F%E4%B8%80%E8%87%B4%E6%80%A7"><span class="nav-number">3.3.1.</span> <span class="nav-text">数据竞争和顺序一致性</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%A1%BA%E5%BA%8F%E4%B8%80%E8%87%B4%E6%80%A7%E6%A8%A1%E5%9E%8B"><span class="nav-number">3.3.2.</span> <span class="nav-text">顺序一致性模型</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#volatile%E7%9A%84%E5%86%85%E5%AD%98%E8%AF%AD%E4%B9%89"><span class="nav-number">3.4.</span> <span class="nav-text">volatile的内存语义</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#volatile%E7%9A%84%E7%89%B9%E6%80%A7"><span class="nav-number">3.4.1.</span> <span class="nav-text">volatile的特性</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#volatile%E5%86%99-%E8%AF%BB%E7%9A%84%E5%86%85%E5%AD%98%E8%AF%AD%E4%B9%89"><span class="nav-number">3.4.2.</span> <span class="nav-text">volatile写 - 读的内存语义</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%94%81%E7%9A%84%E5%86%85%E5%AD%98%E5%AE%9A%E4%B9%89"><span class="nav-number">3.5.</span> <span class="nav-text">锁的内存定义</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%94%81%E7%9A%84%E9%87%8A%E6%94%BE%E5%92%8C%E8%8E%B7%E5%8F%96%E5%86%85%E5%AD%98%E8%AF%AD%E4%B9%89"><span class="nav-number">3.5.1.</span> <span class="nav-text">锁的释放和获取内存语义</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#final%E5%9F%9F%E7%9A%84%E9%87%8D%E6%8E%92%E5%BA%8F%E8%A7%84%E5%88%99"><span class="nav-number">3.6.</span> <span class="nav-text">final域的重排序规则</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%AC%AC%E5%9B%9B%E7%AB%A0-Java%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E5%9F%BA%E7%A1%80"><span class="nav-number">4.</span> <span class="nav-text">第四章 Java并发编程基础</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BA%BF%E7%A8%8B%E7%AE%80%E8%BF%B0"><span class="nav-number">4.1.</span> <span class="nav-text">线程简述</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF%E7%BA%BF%E7%A8%8B"><span class="nav-number">4.1.1.</span> <span class="nav-text">什么是线程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E4%BD%BF%E7%94%A8%E5%A4%9A%E7%BA%BF%E7%A8%8B"><span class="nav-number">4.1.2.</span> <span class="nav-text">为什么要使用多线程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BA%BF%E7%A8%8B%E4%BC%98%E5%85%88%E7%BA%A7"><span class="nav-number">4.1.3.</span> <span class="nav-text">线程优先级</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BA%BF%E7%A8%8B%E7%9A%84%E7%8A%B6%E6%80%81"><span class="nav-number">4.1.4.</span> <span class="nav-text">线程的状态</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Daemon%E7%BA%BF%E7%A8%8B"><span class="nav-number">4.1.5.</span> <span class="nav-text">Daemon线程</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%90%AF%E5%8A%A8%E5%92%8C%E7%BB%88%E6%AD%A2%E7%BA%BF%E7%A8%8B"><span class="nav-number">4.2.</span> <span class="nav-text">启动和终止线程</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9E%84%E9%80%A0%E7%BA%BF%E7%A8%8B"><span class="nav-number">4.2.1.</span> <span class="nav-text">构造线程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%90%AF%E5%8A%A8%E7%BA%BF%E7%A8%8B"><span class="nav-number">4.2.2.</span> <span class="nav-text">启动线程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%90%86%E8%A7%A3%E4%B8%AD%E6%96%AD"><span class="nav-number">4.2.3.</span> <span class="nav-text">理解中断</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BA%BF%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1"><span class="nav-number">4.3.</span> <span class="nav-text">线程间通信</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#volatile%E5%92%8Csynchronized%E5%85%B3%E9%94%AE%E5%AD%97"><span class="nav-number">4.3.1.</span> <span class="nav-text">volatile和synchronized关键字</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%AD%89%E5%BE%85-x2F-%E9%80%9A%E7%9F%A5%E6%9C%BA%E5%88%B6"><span class="nav-number">4.3.2.</span> <span class="nav-text">等待&#x2F;通知机制</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%AD%89%E5%BE%85-x2F-%E9%80%9A%E7%9F%A5%E7%9A%84%E7%BB%8F%E5%85%B8%E8%8C%83%E5%BC%8F"><span class="nav-number">4.3.3.</span> <span class="nav-text">等待&#x2F;通知的经典范式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Thread-join-%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-number">4.3.4.</span> <span class="nav-text">Thread.join()的使用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#ThreadLocal%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-number">4.3.5.</span> <span class="nav-text">ThreadLocal的使用</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%AC%AC%E4%BA%94%E7%AB%A0-Java%E4%B8%AD%E7%9A%84%E9%94%81"><span class="nav-number">5.</span> <span class="nav-text">第五章 Java中的锁</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Lock%E6%8E%A5%E5%8F%A3"><span class="nav-number">5.1.</span> <span class="nav-text">Lock接口</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#AQS"><span class="nav-number">5.2.</span> <span class="nav-text">AQS</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8E%9F%E7%90%86"><span class="nav-number">5.2.1.</span> <span class="nav-text">原理</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#AQS%E4%B8%A4%E7%A7%8D%E8%B5%84%E6%BA%90%E5%85%B1%E4%BA%AB%E6%96%B9%E5%BC%8F"><span class="nav-number">5.2.2.</span> <span class="nav-text">AQS两种资源共享方式</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%8B%AC%E5%8D%A0"><span class="nav-number">5.2.2.1.</span> <span class="nav-text">独占</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%85%B1%E4%BA%AB"><span class="nav-number">5.2.2.2.</span> <span class="nav-text">共享</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#Semaphore"><span class="nav-number">5.2.2.2.1.</span> <span class="nav-text">Semaphore</span></a></li></ol></li><li class="nav-item nav-level-4"><a class="nav-link" href="#CountDownLatch-%E5%80%92%E8%AE%A1%E6%97%B6%E5%99%A8"><span class="nav-number">5.2.2.3.</span> <span class="nav-text">CountDownLatch(倒计时器)</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#CyclicBarrier%EF%BC%88%E5%BE%AA%E7%8E%AF%E6%A0%85%E6%A0%8F%EF%BC%89"><span class="nav-number">5.2.2.4.</span> <span class="nav-text">CyclicBarrier（循环栅栏）</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8F%AF%E9%87%8D%E5%85%A5%E9%94%81"><span class="nav-number">5.2.3.</span> <span class="nav-text">可重入锁</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%AF%BB%E5%86%99%E9%94%81"><span class="nav-number">5.3.</span> <span class="nav-text">读写锁</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%AF%BB%E5%86%99%E9%94%81%E7%9A%84%E6%8E%A5%E5%8F%A3%E5%92%8C%E5%AE%9E%E4%BE%8B"><span class="nav-number">5.3.1.</span> <span class="nav-text">读写锁的接口和实例</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Condition%E6%8E%A5%E5%8F%A3"><span class="nav-number">5.4.</span> <span class="nav-text">Condition接口</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%AE%9E%E7%8E%B0%E5%88%86%E6%9E%90"><span class="nav-number">5.4.0.1.</span> <span class="nav-text">实现分析</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#%E7%AD%89%E5%BE%85%E9%98%9F%E5%88%97"><span class="nav-number">5.4.0.1.1.</span> <span class="nav-text">等待队列</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E7%AD%89%E5%BE%85"><span class="nav-number">5.4.0.1.2.</span> <span class="nav-text">等待</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E9%80%9A%E7%9F%A5"><span class="nav-number">5.4.0.1.3.</span> <span class="nav-text">通知</span></a></li></ol></li></ol></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%AC%AC%E5%85%AD%E7%AB%A0-Java%E5%B9%B6%E5%8F%91%E5%AE%B9%E5%99%A8%E5%92%8C%E6%A1%86%E6%9E%B6"><span class="nav-number">6.</span> <span class="nav-text">第六章 Java并发容器和框架</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#ConcurrentHashMap"><span class="nav-number">6.1.</span> <span class="nav-text">ConcurrentHashMap</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E4%BD%BF%E7%94%A8ConcurrentHashMap"><span class="nav-number">6.1.1.</span> <span class="nav-text">为什么要使用ConcurrentHashMap?</span></a></li></ol></li></ol></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="yorn"
      src="/myblog/uploads/head.jpg">
  <p class="site-author-name" itemprop="name">yorn</p>
  <div class="site-description" itemprop="description">足够专注才能成功</div>
</div>
<div class="site-state-wrap site-overview-item animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/myblog/archives/">
          <span class="site-state-item-count">53</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/myblog/categories/">
        <span class="site-state-item-count">13</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/myblog/tags/">
        <span class="site-state-item-count">19</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author site-overview-item animated">
      <span class="links-of-author-item">
        <a href="https://github.com/wang-chen1119" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;wang-chen1119" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:w1905989051@gmail.com" title="E-Mail → mailto:w1905989051@gmail.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>
  <div class="cc-license site-overview-item animated" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" class="cc-opacity" rel="noopener" target="_blank"><img src="https://cdnjs.cloudflare.com/ajax/libs/creativecommons-vocabulary/2020.11.3/assets/license_badges/small/by_nc_sa.svg" alt="Creative Commons"></a>
  </div>


  <div class="links-of-blogroll site-overview-item animated">
    <div class="links-of-blogroll-title"><i class="fa fa-globe fa-fw"></i>
      Links
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="https://blog.csdn.net/qq_51088445" title="https:&#x2F;&#x2F;blog.csdn.net&#x2F;qq_51088445" rel="noopener" target="_blank">CSDN</a>
        </li>
    </ul>
  </div>

        </div>
      </div>
    </div>
  </aside>
  <div class="sidebar-dimmer"></div>


    </header>

    
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>
  <a role="button" class="book-mark-link book-mark-link-fixed"></a>

  <a href="https://github.com/wang-chen1119" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://wang-chen1119.gitee.io/myblog/2022/10/29/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/myblog/uploads/head.jpg">
      <meta itemprop="name" content="yorn">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Yorn's Notes">
      <meta itemprop="description" content="足够专注才能成功">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="Java并发编程的艺术读书笔记 | Yorn's Notes">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          Java并发编程的艺术读书笔记
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      

      <time title="创建时间：2022-10-29 13:32:16 / 修改时间：13:31:55" itemprop="dateCreated datePublished" datetime="2022-10-29T13:32:16+08:00">2022-10-29</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/myblog/categories/%E5%B9%B6%E5%8F%91/" itemprop="url" rel="index"><span itemprop="name">并发</span></a>
        </span>
    </span>

  
    <span class="post-meta-break"></span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>9k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>8 分钟</span>
    </span>
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
        <h1 id="第一章-并发编程的挑战"><a href="#第一章-并发编程的挑战" class="headerlink" title="第一章 并发编程的挑战"></a>第一章 并发编程的挑战</h1><h2 id="上下文切换"><a href="#上下文切换" class="headerlink" title="上下文切换"></a>上下文切换</h2><p>CPU通过为每个线程分配CPU时间片来支持支持单核处理器执行多线程代码。时间片非常短，CPU通过不断切换线程，让我们认为多个线程是同时执行的。</p>
<p>上下文切换 ：当线程执行完一个时间片后切换线程占有CPU，这是需要保存当前的执行状态，让再次切换到此线程时加载保存的执行状态继续执行。</p>
<h2 id="如何减少上下文切换"><a href="#如何减少上下文切换" class="headerlink" title="如何减少上下文切换"></a>如何减少上下文切换</h2><ul>
<li>无锁并发编程 ：多线程竞争锁时，会引起上下文切换，所以多线程处理数据时，可以用一些办法来避免使用锁，如将数据的ID按照Hash算法取模分段，不同的线程处理不同段的数据</li>
<li>CAS算法 ： Java的Atomic包使用CAS算法来更新数据，而不需要加锁</li>
<li>使用最少线程 ： 避免创建不需要的线程，比如任务很少，但是创建了很多线程来处理，这样会造成大量线程都处于等待状态</li>
<li>协程：在单线程里实现多任务的调度，并在单线程里维持多个任务间的切换</li>
</ul>
<h2 id="死锁"><a href="#死锁" class="headerlink" title="死锁"></a>死锁</h2><p>死锁 ： 两个或多个线程互相占有了对方所需要的资源，如果没有外力作用，这些线程无法继续进行下去永远处于互相等待的状态</p>
<p>避免死锁的几个方法：</p>
<ul>
<li>避免一个线程同时获取多个锁</li>
<li>避免一个线程在锁内同时占有多个资源，尽量保证每个所只占有一个资源</li>
<li>尝试使用定时锁，使用lock.tryLock（timeout）来替代使用内部锁机制</li>
<li>对于数据库锁，加锁和解锁必须在一个数据库连接里，否则会出现解锁失败的情况。</li>
</ul>
<h1 id="第二章Java并发机制的底层实现"><a href="#第二章Java并发机制的底层实现" class="headerlink" title="第二章Java并发机制的底层实现"></a>第二章Java并发机制的底层实现</h1><h2 id="volatile的应用"><a href="#volatile的应用" class="headerlink" title="volatile的应用"></a>volatile的应用</h2><blockquote>
<p>volatile是轻量级的synchronized，他保证共享变量的可见性(即一个线程对共享变量修改时，其他线程是能读到修改后的值的)</p>
<p>使用volatile不会引起上下文的切换和线程调度，所以执行成本更低</p>
</blockquote>
<h3 id="volatile的定义和实现原理"><a href="#volatile的定义和实现原理" class="headerlink" title="volatile的定义和实现原理"></a>volatile的定义和实现原理</h3><blockquote>
<p>Java语言规范第3版中对volatile的定义如下：Java编程语言允许线程访问共享变量，为了 确保共享变量能被准确和一致地更新，线程应该确保通过排他锁单独获得这个变量。Java语言 提供了volatile，在某些情况下比锁要更加方便。如果一个字段被声明成volatile，Java线程内存 模型确保所有线程看到这个变量的值是一致的</p>
</blockquote>
<p><strong>内存屏障的概念</strong></p>
<p>内存屏障是一组处理器指令，用于实现对内存操作的顺序限制</p>
<h4 id="volatile如何保证可见性"><a href="#volatile如何保证可见性" class="headerlink" title="volatile如何保证可见性"></a>volatile如何保证可见性</h4><p>使用Lock前缀的指令</p>
<p>两条实现原则</p>
<ol>
<li><p>Lock前缀指令会引起处理器缓存写回到内存</p>
<p> 在执行指令期间声明LOCK#信号，保证在该信号期间处理器可以独占任何共享 —&gt; 锁缓存一般是</p>
</li>
<li><p>一个处理器的缓存写回到内存中会导致其他处理器的缓存无效    —-&gt; 处理器使用嗅探技术保证它的内部缓存、系统内存和其他处理器的 缓存的数据在总线上保持一致</p>
</li>
</ol>
<h2 id="synchronized的实现原理和应用"><a href="#synchronized的实现原理和应用" class="headerlink" title="synchronized的实现原理和应用"></a>synchronized的实现原理和应用</h2><p>锁的具体表现形式</p>
<ol>
<li>对于普通同步方法，锁是当前实例对象。</li>
<li>对于静态同步方法，锁是当前类的Class对象</li>
<li>对于同步方法块，锁是Synchonized括号里配置的对象</li>
</ol>
<p><strong>关于sync在jvm底层的实现</strong></p>
<p>sync同步代码块的实现使用的是monitorenter和monitorexit，其中monitorenter指令指向同步代码块的开始文职，monitorexit指令则指明同步代码块结束的位置</p>
<p>当执行到<code>monitorenter</code>指令时，线程试图获取锁也是就对象监视器<code>monitor</code>的持有权。</p>
<p><img src="https://image-1305623006.cos.ap-nanjing.myqcloud.com/synchronized-get-lock-code-block.f8021972.png" alt="执行 monitorenter 获取锁"></p>
<p><img src="https://image-1305623006.cos.ap-nanjing.myqcloud.com/synchronized-release-lock-block.c8310368.png" alt="执行 monitorexit 释放锁"></p>
<p><strong>锁类和锁实例对象的区别</strong></p>
<ul>
<li>对普通方法加锁获取对象锁，如果两个通过sync加锁的普通方法如果当前对象正在执行其中一个方法，那么另一个方法需要等到当前对象锁释放才能执行</li>
<li>如果其中一个方法没有被sync加锁，那么某个线程获得了对象锁，其他线程仍然可以去访问没有进行同步的方法或者代码块。加锁的方法(同步方法)与普通方法是不互斥的</li>
<li><strong>某个线程进入同步方法获得对象锁，那么其他线程访问这里对象的同步方法时，必须等待或者阻塞</strong></li>
<li>一个类可以有多个实例对象</li>
</ul>
<p><strong>Synchronized和lock的区别</strong></p>
<ol>
<li>性能不一样：资源竞争激烈的情况下，lock性能比synchronized锁好，竞争不激烈的情况下，synchronized比lock锁性能要好，synchronized根据锁的竞争情况会有锁升级的过程。</li>
<li>锁机制不一样：synchronized是JVM层面实现的，系统监控锁的释放与否(对于方法会加ACC_SYNCHRONIZED 代码块的话通过monitor(监视器)来实现)</li>
<li>用法不一样：synchronize可以用在代码块上，方法上。lock只能写在代码里，不能直接修改方法。</li>
<li>sync线程1获得锁并且阻塞，线程2会一直等待下去；lock锁不会一直等待下去，会尝试获取锁：lock.tryLock()</li>
<li>syn可重入锁，不可中断，非公平；lock可重入锁，可判断锁，可以公平也可以不公平</li>
<li>syn无法获取锁的状态，lock可以判断是否获得了锁</li>
</ol>
<p>java锁的升级和对比</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_51088445/article/details/122724770">(31条消息) java锁的升级和对比_逗号8080的博客-CSDN博客</a></p>
<h2 id="原子操作的实现原理"><a href="#原子操作的实现原理" class="headerlink" title="原子操作的实现原理"></a>原子操作的实现原理</h2><h3 id="术语定义"><a href="#术语定义" class="headerlink" title="术语定义"></a>术语定义</h3><p><img src="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220219162330599.png" alt="image-20220219162330599"></p>
<h3 id="如何实现原子操作"><a href="#如何实现原子操作" class="headerlink" title="如何实现原子操作"></a>如何实现原子操作</h3><ol>
<li><p>通过总线锁保证原子性</p>
<p> 使用处理器提供的一个LOCK＃信号，当一个处理器在总线上输出此信时，其他处理器的请求将被阻塞住，那么该 处理器可以独占共享内存</p>
</li>
<li><p>缓存锁保证原子性</p>
<p> 谓“缓存锁定”是指内存区域如果被缓存在处理器的缓存行中，并且在Lock操作期间被锁定，那么当它执行锁操作回写到内存时，处理器不在总线上声 言LOCK＃信号，而是修改内部的内存地址，并允许它的缓存一致性机制来保证操作的原子 性，因为缓存一致性机制会阻止同时修改由两个以上处理器缓存的内存区域数据，当其他处 理器回写已被锁定的缓存行的数据时，会使缓存行无效</p>
</li>
</ol>
<p><em>不会使用缓存锁定的两种情况</em></p>
<ol>
<li>操作的数据不能缓存在处理器内部或操作的数据占据多个缓存行</li>
<li>有些处理器不支持</li>
</ol>
<h3 id="Java实现原子操作"><a href="#Java实现原子操作" class="headerlink" title="Java实现原子操作"></a>Java实现原子操作</h3><ol>
<li><p>使用CAS</p>
<p> 自旋CAS实现的基本思路就是循环进行CAS操作直到成功为止。</p>
<p> 缺点</p>
<ul>
<li>ABA问题 ： 一个值原来是A改成了B又变回了A，CAS检查时他的值没有变化但实际是变化了。 解决方法 ： 版本号</li>
<li>循环开销时间大</li>
<li>只能保证一个共享变量的原子操作</li>
</ul>
</li>
<li><p>锁机制</p>
</li>
</ol>
<h1 id="第三章Java内存模型"><a href="#第三章Java内存模型" class="headerlink" title="第三章Java内存模型"></a>第三章Java内存模型</h1><h2 id="Java内存模型的基础"><a href="#Java内存模型的基础" class="headerlink" title="Java内存模型的基础"></a>Java内存模型的基础</h2><h3 id="并发编程模型的两个关键问题"><a href="#并发编程模型的两个关键问题" class="headerlink" title="并发编程模型的两个关键问题"></a>并发编程模型的两个关键问题</h3><ol>
<li><p>线程通信</p>
<p> 通信是指线程之间以何种机制来交换信息</p>
<p> 通信的两种方式</p>
<ul>
<li>共享内存 ： 线程间共享程序的公共状态，通过读写公共状态进行隐式通信</li>
<li>消息传递 ： 线程通过发送消息进行显式通信</li>
</ul>
</li>
<li><p>线程同步</p>
<p> 同步指程序中用于控制不同线程间操作发生相对顺序的机制</p>
<p> 共享内存并发模型中 同步是显示进行的。 程序员显式的指定某个方法或某个代码需要在线程之间互斥执行</p>
<p> 消息传递的并发模型当中 消息的发送在消息的接收之前，同步是隐式进行的</p>
</li>
</ol>
<p><strong>Java采用的是共享内存模型</strong></p>
<h3 id="Java内存模型的抽象结构"><a href="#Java内存模型的抽象结构" class="headerlink" title="Java内存模型的抽象结构"></a>Java内存模型的抽象结构</h3><p><strong>JMM  –&gt; Java内存模型</strong></p>
<p>从并发角度来看Java内存模型</p>
<p><img src="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220220151156707.png" alt="image-20220220151156707"></p>
<p>线程A B通信的步骤</p>
<ol>
<li>线程A将本地内存中更新过得变量刷新到主内存中去</li>
<li>线程B去主内存中读取刷新过得共享变量</li>
</ol>
<h3 id="从源代码到指令序列的重排序"><a href="#从源代码到指令序列的重排序" class="headerlink" title="从源代码到指令序列的重排序"></a>从源代码到指令序列的重排序</h3><p>三种重排序</p>
<ol>
<li>编译器优化的重排序</li>
<li>指令级并行的重排序</li>
<li>内存系统的重排序</li>
</ol>
<p><img src="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220220151853914.png" alt="image-20220220151853914"></p>
<blockquote>
<p>JMM属于语言级的内存模型，它确保在不同的编译器和不同的处理器平台之上，通过禁止特定类型的编译器重排序和处理器重排序，为程序员提供一致的内存可见性保证。</p>
</blockquote>
<h3 id="内存屏障类型"><a href="#内存屏障类型" class="headerlink" title="内存屏障类型"></a>内存屏障类型</h3><p><img src="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220220152417487.png" alt="image-20220220152417487"></p>
<h2 id="重排序"><a href="#重排序" class="headerlink" title="重排序"></a>重排序</h2><blockquote>
<p>重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段。   —– 《Java并发编程的艺术》</p>
</blockquote>
<h3 id="数据依赖性"><a href="#数据依赖性" class="headerlink" title="数据依赖性"></a>数据依赖性</h3><p>如果两个操作访问同一个变量，如果其中一个操作为写操作，此时两个操作之间就包括数据依赖性</p>
<p>数据依赖类型</p>
<ol>
<li>写后读    如  a &#x3D; 1  b &#x3D; a</li>
<li>写后写    如 a &#x3D; 1 a &#x3D; 2</li>
<li>读后写    如  a &#x3D; b  b &#x3D; 1</li>
</ol>
<p>这三种情况如果发生指令重排序，那么程序的执行结果就会发生改变</p>
<p><strong>编译器和处理器在重排序时，会遵 守数据依赖性，编译器和处理器不会改变存在数据依赖关系的两个操作的执行顺序。</strong></p>
<h3 id="as-if-serial"><a href="#as-if-serial" class="headerlink" title="as-if-serial"></a>as-if-serial</h3><blockquote>
<p>as-if-serial语义的意思是：不管怎么重排序（编译器和处理器为了提高并行度），（单线程） 程序的执行结果不能被改变。编译器、runtime和处理器都必须遵守as-if-serial语义。 </p>
</blockquote>
<h3 id="重排序对多线程的影响"><a href="#重排序对多线程的影响" class="headerlink" title="重排序对多线程的影响"></a>重排序对多线程的影响</h3><p>实例代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">ReorderExample</span></span><br><span class="line">&#123; </span><br><span class="line">    <span class="type">int</span> <span class="variable">a</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">    <span class="type">boolean</span> <span class="variable">flag</span> <span class="operator">=</span> <span class="literal">false</span>; </span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">writer</span><span class="params">()</span> &#123;</span><br><span class="line">        a = <span class="number">1</span>; <span class="comment">// 1</span></span><br><span class="line">        flag = <span class="literal">true</span>; <span class="comment">// 2 </span></span><br><span class="line">    &#125;</span><br><span class="line">    Public <span class="keyword">void</span> <span class="title function_">reader</span><span class="params">()</span> &#123; </span><br><span class="line">        <span class="keyword">if</span> (flag) &#123;  <span class="comment">// 3 </span></span><br><span class="line">            <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> a * a; <span class="comment">// 4</span></span><br><span class="line">            …… </span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>假设有两个线程A，B ，A首先执行writer()，然后B执行reader()方法，当B在执行 4 时能不能看到 A在操作1时的 a &#x3D; 1呢 ？</p>
<p>答案 ： **不一定能看到 **</p>
<p>操作 1 2 没有数据依赖关系，所以两个操作是能被重排序的，操作 3 4也没有数据依赖关系，也是可以重排序的</p>
<blockquote>
<p>在单线程程序中，对存在控制依赖的操作重排序，不会改变执行结果（这也是as-if-serial 语义允许对存在控制依赖的操作做重排序的原因）；但在多线程程序中，对存在控制依赖的操作重排序，可能会改变程序的执行结果。</p>
</blockquote>
<h2 id="顺序一致性"><a href="#顺序一致性" class="headerlink" title="顺序一致性"></a>顺序一致性</h2><h3 id="数据竞争和顺序一致性"><a href="#数据竞争和顺序一致性" class="headerlink" title="数据竞争和顺序一致性"></a>数据竞争和顺序一致性</h3><blockquote>
<p>Java内存模型规范对数据竞争的定义</p>
<p>在一个线程中写一个变量，在另一个线程读同一个变量，而且读和写没有通过同步来排序。</p>
</blockquote>
<p>JMM对正确同步的多线程程序做了如下保证：</p>
<p>程序的执行结果与程序在顺序一致性内存模型中的执行结果相同</p>
<h3 id="顺序一致性模型"><a href="#顺序一致性模型" class="headerlink" title="顺序一致性模型"></a>顺序一致性模型</h3><p><strong>两大特征：</strong></p>
<ol>
<li>一个线程中的所有操作必须按照程序的顺序来执行</li>
<li>（不管程序是否同步）所有线程都只能看到一个单一的操作执行顺序。在顺序一致性内存模型中，每个操作都必须原子执行且立刻对所有线程可见。</li>
</ol>
<h2 id="volatile的内存语义"><a href="#volatile的内存语义" class="headerlink" title="volatile的内存语义"></a>volatile的内存语义</h2><h3 id="volatile的特性"><a href="#volatile的特性" class="headerlink" title="volatile的特性"></a>volatile的特性</h3><p>可见性 ： 对于一个volatile变量的读，总是能看到对这个volatile变量的最后的写入</p>
<p>原子性 ： 对任意单个volatile变量的读写具有原子性。 但类似于volatile++这种复合操作不具有原子性</p>
<h3 id="volatile写-读的内存语义"><a href="#volatile写-读的内存语义" class="headerlink" title="volatile写 - 读的内存语义"></a>volatile写 - 读的内存语义</h3><p>当写一个volatile变量时，JMM会把该线程对应的本地内存中的共享变量值刷新到主内存。</p>
<p>当读一个volatile变量时，JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取共享变量。</p>
<h2 id="锁的内存定义"><a href="#锁的内存定义" class="headerlink" title="锁的内存定义"></a>锁的内存定义</h2><h3 id="锁的释放和获取内存语义"><a href="#锁的释放和获取内存语义" class="headerlink" title="锁的释放和获取内存语义"></a>锁的释放和获取内存语义</h3><p>线程释放锁时，JMM会把该线程对应的本地内存中的共享变量刷新主内存中。</p>
<p>当线程获取锁时，JMM会把该线程对应的本地内存置为无效。从而使得被监视器保护的 临界区代码必须从主内存中读取共享变量。</p>
<h2 id="final域的重排序规则"><a href="#final域的重排序规则" class="headerlink" title="final域的重排序规则"></a>final域的重排序规则</h2><p>对于final域，编译器和处理器要遵守两个重排序规则。 </p>
<p>1）在构造函数内对一个final域的写入，与随后把这个被构造对象的引用赋值给一个引用 变量，这两个操作之间不能重排序。 </p>
<p>2）初次读一个包含final域的对象的引用，与随后初次读这个final域，这两个操作之间不能重排序。 </p>
<h1 id="第四章-Java并发编程基础"><a href="#第四章-Java并发编程基础" class="headerlink" title="第四章 Java并发编程基础"></a>第四章 Java并发编程基础</h1><h2 id="线程简述"><a href="#线程简述" class="headerlink" title="线程简述"></a>线程简述</h2><h3 id="什么是线程"><a href="#什么是线程" class="headerlink" title="什么是线程"></a>什么是线程</h3><blockquote>
<p>在我们启动一个程序时，会为他创建一个进程，而现代最操作系统调度的最小单元是线程，也称作轻量级进程</p>
</blockquote>
<h3 id="为什么要使用多线程"><a href="#为什么要使用多线程" class="headerlink" title="为什么要使用多线程"></a>为什么要使用多线程</h3><ol>
<li>更多的处理核心</li>
<li>更快的响应时间</li>
<li>更好的编程模型</li>
</ol>
<h3 id="线程优先级"><a href="#线程优先级" class="headerlink" title="线程优先级"></a>线程优先级</h3><p>线程优先级决定线程需要多或少分配一些处理器资源的线程属性</p>
<p>Java线程中通过一个整型成员变量priority来控制优先级，优先级的范围从1~10，线程构建时可以通过setPriority(int) 方法来修改优先级，默认优先级是5</p>
<p>优先级高的线程分配时间片的数量要多于优先级低的线程</p>
<h3 id="线程的状态"><a href="#线程的状态" class="headerlink" title="线程的状态"></a>线程的状态</h3><p>六种状态</p>
<table>
<thead>
<tr>
<th>状态名称</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>NEW</td>
<td>初始状态。线程被构建但还未调用start()方法</td>
</tr>
<tr>
<td>RUNNABLE</td>
<td>运行状态，Java线程将操作系统中的就绪态和运行态统称为“运行中”</td>
</tr>
<tr>
<td>BLOCKED</td>
<td>阻塞态</td>
</tr>
<tr>
<td>WAITING</td>
<td>等待状态，表示线程进入等待状态，进入该状态表示当前线程需要等待其他线程做出一些特定动作</td>
</tr>
<tr>
<td>TIME_WAITING</td>
<td>超时等待，可以在指定的时间返回</td>
</tr>
<tr>
<td>TERMINATED</td>
<td>终止状态</td>
</tr>
</tbody></table>
<p><img src="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220222194052103.png" alt="image-20220222194052103"></p>
<h3 id="Daemon线程"><a href="#Daemon线程" class="headerlink" title="Daemon线程"></a>Daemon线程</h3><blockquote>
<p>Daemon线程是一种支持型线程，因为它主要被用作程序中后台调度以及支持性工作。这意味着，当一个Java虚拟机中不存在非Daemon线程的时候，Java虚拟机将会退出。可以通过调用Thread.setDaemon(true)将线程设置为Daemon线程</p>
</blockquote>
<h2 id="启动和终止线程"><a href="#启动和终止线程" class="headerlink" title="启动和终止线程"></a>启动和终止线程</h2><h3 id="构造线程"><a href="#构造线程" class="headerlink" title="构造线程"></a>构造线程</h3><p>在运行线程之前首先要构造一个线程对象，线程对象在构造的时候需要提供线程所需要的属性，如线程所属的线程组、线程优先级、是否是Daemon线程等信息</p>
<p>java.lang.Thread 中线程初始化的部分</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">init</span><span class="params">(ThreadGroup g, Runnable target, String name,<span class="type">long</span> stackSize, AccessControlContext acc)</span> &#123; </span><br><span class="line">    <span class="keyword">if</span> (name == <span class="literal">null</span>) &#123; </span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">NullPointerException</span>(<span class="string">&quot;name cannot be null&quot;</span>); </span><br><span class="line">    &#125;<span class="comment">// 当前线程就是该线程的父线程 </span></span><br><span class="line">    <span class="type">Thread</span> <span class="variable">parent</span> <span class="operator">=</span> currentThread(); </span><br><span class="line">    <span class="built_in">this</span>.group = g; </span><br><span class="line">    <span class="comment">// 将daemon、priority属性设置为父线程的对应属性 </span></span><br><span class="line">    <span class="built_in">this</span>.daemon = parent.isDaemon();</span><br><span class="line">    <span class="built_in">this</span>.priority = parent.getPriority();</span><br><span class="line">    <span class="built_in">this</span>.name = name.toCharArray();</span><br><span class="line">    <span class="built_in">this</span>.target = target; </span><br><span class="line">    setPriority(priority); <span class="comment">// 将父线程的InheritableThreadLocal复制过来 </span></span><br><span class="line">    <span class="keyword">if</span> (parent.inheritableThreadLocals != <span class="literal">null</span>) <span class="built_in">this</span>.inheritableThreadLocals=ThreadLocal.createInheritedMap(parent. inheritableThreadLocals); </span><br><span class="line">    <span class="comment">// 分配一个线程ID </span></span><br><span class="line">    tid = nextThreadID();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="启动线程"><a href="#启动线程" class="headerlink" title="启动线程"></a>启动线程</h3><p>start()方法，线程初始化完成之后，调用start方法就可以启动线程。当前线程(parent)线程同步告知Java虚拟机，只要线程规划器空闲，就立即调用start()方法的线程</p>
<h3 id="理解中断"><a href="#理解中断" class="headerlink" title="理解中断"></a>理解中断</h3><blockquote>
<p>中断可以理解为线程的一个标识位属性，它表示一个运行中的线程是否被其他线程进行了中断操作</p>
</blockquote>
<p>interrupt()  –&gt; 其他线程通过调用该线程的interrupt() 方法进行中断操作</p>
<p>isInterrupted() –&gt; 通过isInterrupted()方法来判断是否被中断</p>
<p>调用静态方法Thread.interrupted()对当前线程的中断标识位进行复位</p>
<p>线程如果已经处于终结状态，即使线程被中断过，在调用该线程对象的isInterrupted()时依然会返回false</p>
<h2 id="线程间通信"><a href="#线程间通信" class="headerlink" title="线程间通信"></a>线程间通信</h2><h3 id="volatile和synchronized关键字"><a href="#volatile和synchronized关键字" class="headerlink" title="volatile和synchronized关键字"></a>volatile和synchronized关键字</h3><p>volatile，对volatile修饰的字段进行修改必须同步刷新回共享内存，对该变量的访问需要从共享内存中获取</p>
<p>synchronized，d可以修饰方法或者以同步块的形式来进行使用，它主要确保多个线程 在同一个时刻，只能有一个线程处于方法或者同步块中，它保证了线程对变量访问的可见性和排他性</p>
<h3 id="等待-x2F-通知机制"><a href="#等待-x2F-通知机制" class="headerlink" title="等待&#x2F;通知机制"></a>等待&#x2F;通知机制</h3><p>等待&#x2F;通知的相关方法是任意Java对象都具备的，因为这些方法被定义在所有对象的超类 java.lang.Object上，</p>
<p><img src="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220222201040273.png" alt="image-20220222201040273"></p>
<h3 id="等待-x2F-通知的经典范式"><a href="#等待-x2F-通知的经典范式" class="headerlink" title="等待&#x2F;通知的经典范式"></a>等待&#x2F;通知的经典范式</h3><p>等待方 ：</p>
<p>1）获取对象的锁。 </p>
<p>2）如果条件不满足，那么调用对象的wait()方法，被通知后仍要检查条件。 </p>
<p>3）条件满足则执行对应的逻辑。</p>
<p>通知方 ：</p>
<p>1）获得对象的锁。 </p>
<p>2）改变条件。 </p>
<p>3）通知所有等待在对象上的线程。 </p>
<h3 id="Thread-join-的使用"><a href="#Thread-join-的使用" class="headerlink" title="Thread.join()的使用"></a>Thread.join()的使用</h3><p>如果一个线程A执行了thread.join()语句，其含义是：当前线程A等待thread线程终止之后才从thread.join()返回</p>
<h3 id="ThreadLocal的使用"><a href="#ThreadLocal的使用" class="headerlink" title="ThreadLocal的使用"></a>ThreadLocal的使用</h3><p>ThreadLocal，即线程变量，是一个以ThreadLocal对象为键、任意对象为值的存储结构。</p>
<p>在访问该变量时线程会有拷贝一份该变量，对变量的操作都是在自己本地内存上进行操作，这样就不会产生线程不安全的问题</p>
<p>推荐文章</p>
<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/fsmly/p/11020641.html">Java中的ThreadLocal详解 - 夏末秋涼 - 博客园 (cnblogs.com)</a></p>
<h1 id="第五章-Java中的锁"><a href="#第五章-Java中的锁" class="headerlink" title="第五章 Java中的锁"></a>第五章 Java中的锁</h1><h2 id="Lock接口"><a href="#Lock接口" class="headerlink" title="Lock接口"></a>Lock接口</h2><p>具有与synchronized关键字类似的同步功能，但是他能显示的上锁和解锁</p>
<p>有着锁获取和锁释放的可操作性，可中断行，超时获取锁等同步特征</p>
<p><img src="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220226105010740.png" alt="image-20220226105010740"></p>
<h2 id="AQS"><a href="#AQS" class="headerlink" title="AQS"></a>AQS</h2><h3 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h3><p>如果被请求的有效共享资源为空闲状态，那么将请求的线程设置成工作状态，资源被设计为占有状态，如果请求的资源被占有那么需要一套阻塞唤醒机制，AQS采用CLH队列锁来实现</p>
<blockquote>
<p>CLH队列是一个虚拟的双向队列</p>
</blockquote>
<p><img src="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220226112938315.png" alt="image-20220226112938315"></p>
<p>AQS采用一个int变量来表示同步状态</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">volatile</span> <span class="type">int</span> state;<span class="comment">//共享变量，使用volatile修饰保证线程可见性</span></span><br></pre></td></tr></table></figure>

<p>采用CAS来对该值进行原子操作实现对该值的修改</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//返回同步状态的当前值</span></span><br><span class="line"><span class="keyword">protected</span> <span class="keyword">final</span> <span class="type">int</span> <span class="title function_">getState</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> state;</span><br><span class="line">&#125;</span><br><span class="line"> <span class="comment">// 设置同步状态的值</span></span><br><span class="line"><span class="keyword">protected</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">setState</span><span class="params">(<span class="type">int</span> newState)</span> &#123;</span><br><span class="line">        state = newState;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//原子地（CAS操作）将同步状态值设置为给定值update如果当前同步状态的值等于expect（期望值）</span></span><br><span class="line"><span class="keyword">protected</span> <span class="keyword">final</span> <span class="type">boolean</span> <span class="title function_">compareAndSetState</span><span class="params">(<span class="type">int</span> expect, <span class="type">int</span> update)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> unsafe.compareAndSwapInt(<span class="built_in">this</span>, stateOffset, expect, update);</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<h3 id="AQS两种资源共享方式"><a href="#AQS两种资源共享方式" class="headerlink" title="AQS两种资源共享方式"></a>AQS两种资源共享方式</h3><h4 id="独占"><a href="#独占" class="headerlink" title="独占"></a>独占</h4><p>只有一个线程能执行 如 ReentrantLock</p>
<p><strong>公平锁和非公平锁</strong></p>
<p><strong>公平锁</strong> ： 线程按照在队列中的排队顺序，先到先拿锁</p>
<p><strong>非公平锁</strong> ： 线程通过CAS操作抢锁，没抢到线程加入队列中阻塞等待唤醒</p>
<h4 id="共享"><a href="#共享" class="headerlink" title="共享"></a>共享</h4><p>多线程可同时执行，</p>
<p>如：Semaphore&#x2F;CountDownLatch。Semaphore、CountDownLatCh、 CyclicBarrier、ReadWriteLock</p>
<h5 id="Semaphore"><a href="#Semaphore" class="headerlink" title="Semaphore"></a>Semaphore</h5><p><code>synchronized</code> 和 <code>ReentrantLock</code> 都是一次只允许一个线程访问某个资源，<code>Semaphore</code>(信号量)可以指定多个线程同时访问某个资源</p>
<p>提供许可证，线程获取许可证来操作资源。</p>
<p>两种模式</p>
<p><strong>公平模式</strong> ： 通过调动<code>acquire()</code>方法的顺序就是获取许可证的顺序，遵循FIFP</p>
<p><strong>非公平模式</strong> ： 抢占式</p>
<h4 id="CountDownLatch-倒计时器"><a href="#CountDownLatch-倒计时器" class="headerlink" title="CountDownLatch(倒计时器)"></a>CountDownLatch(倒计时器)</h4><p>允许<code>count</code>个线程阻塞在一个地方，直到所有线程的任务都执行完毕</p>
<p>线程调用 <code>countDown</code>方法时使用<code>tryReleaseShared</code> 方法以CAS的操作来减少state，直到<code>state</code>为0</p>
<p>调用<code>await()</code>方法如果<code>state</code>不为0就会一直阻塞，<code>CountDownLatch</code>通过自旋CAS判断<code>state == 0</code></p>
<p>如果<code>state == 0 </code>则释放所有等待的线程，<code>await()</code>方法之后的语句执行</p>
<p>两种用法：</p>
<ol>
<li>某一线程在开始运行前等待n个线程执行完毕</li>
<li>实现多个线程开始执行任务时的最大并行性</li>
</ol>
<h4 id="CyclicBarrier（循环栅栏）"><a href="#CyclicBarrier（循环栅栏）" class="headerlink" title="CyclicBarrier（循环栅栏）"></a>CyclicBarrier（循环栅栏）</h4><p>让一组线程到达一个屏障（也可以叫同步点）时被阻塞，直到最后一个线程到达屏障时，屏障才会开门，所有被屏障拦截的线程才会继续干活</p>
<p>默认的构造方法是 <code>CyclicBarrier(int parties)</code>，其参数表示屏障拦截的线程数量，每个线程调用 <code>await()</code> 方法告诉 <code>CyclicBarrier</code> 我已经到达了屏障，然后当前线程被阻塞。</p>
<h3 id="可重入锁"><a href="#可重入锁" class="headerlink" title="可重入锁"></a>可重入锁</h3><p>该锁支持一个线程对资源的重复加锁</p>
<p>实现重进入需要解决的两个问题</p>
<ol>
<li><p>线程再次获取锁 ： 需要识别获取所得线程是否为当前占据所得线程，如果时则再次成功获取</p>
</li>
<li><p>所得最终释放  ： 线程重复n次获取了锁，随后在第n次释放该锁后，其他线程能够获取到 </p>
<p> 该锁</p>
</li>
</ol>
<h2 id="读写锁"><a href="#读写锁" class="headerlink" title="读写锁"></a>读写锁</h2><p>读锁和写锁两个方法</p>
<p>readLock() 和 writeLock()方法</p>
<p>读写锁在同一时间可以允许多个读线程访问，在写进程访问时所有的读线程和写线程均会被阻塞。</p>
<h3 id="读写锁的接口和实例"><a href="#读写锁的接口和实例" class="headerlink" title="读写锁的接口和实例"></a>读写锁的接口和实例</h3><p><img src="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220227132915283.png" alt="image-20220227132915283"></p>
<h2 id="Condition接口"><a href="#Condition接口" class="headerlink" title="Condition接口"></a>Condition接口</h2><p>Condition是在java 1.5中才出现的，它用来替代传统的Object的wait()、notify()实现线程间的协作，相比使用Object的wait()、notify()，使用Condition的await()、signal()这种方式实现线程间协作更加安全和高效。因此通常来说比较推荐使用Condition，阻塞队列实际上是使用了Condition来模拟线程间协作。</p>
<p>Condition定义了等待&#x2F;通知两种类型的方法，当前线程调用这些方法时需要提前获取到与Condition对象关联的锁</p>
<p>Condition是依赖于Lock对象的</p>
<p><img src="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220227133437241.png" alt="image-20220227133437241"></p>
<h4 id="实现分析"><a href="#实现分析" class="headerlink" title="实现分析"></a>实现分析</h4><h5 id="等待队列"><a href="#等待队列" class="headerlink" title="等待队列"></a>等待队列</h5><p>等待队列是一个FIFO的队列，队列中的每个节点都包含了一个线程引用，这个线程就是在condition对象上等待的线程</p>
<p>如果一个线程执行了await()方法，该线程会释放锁构成节点加入等待队列并进入等待状态。</p>
<p>Lock(同步器)中一个对象有一个同步队列和多个等待队列</p>
<p><img src="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220227134154343.png" alt="image-20220227134154343"></p>
<p><img src="https://image-1305623006.cos.ap-nanjing.myqcloud.com/image-20220227135146782.png" alt="image-20220227135146782"></p>
<h5 id="等待"><a href="#等待" class="headerlink" title="等待"></a>等待</h5><p>调用Condition的await()方法（或者以await开头的方法），会使当前线程进入等待队列并释 放锁，同时线程状态变为等待状态。当从await()方法返回时，当前线程一定获取了Condition相 关联的锁</p>
<blockquote>
<p>同步队列的首节点并不会直接加入等待队列，而是通过addConditionWaiter()方法把当前线程构造成一个新的节点并将其加入等待队列中。 </p>
</blockquote>
<h5 id="通知"><a href="#通知" class="headerlink" title="通知"></a>通知</h5><blockquote>
<p>调用Condition的signal()方法，将会唤醒在等待队列中等待时间最长的节点（首节点），在唤醒节点之前，会将节点移到同步队列中</p>
</blockquote>
<h1 id="第六章-Java并发容器和框架"><a href="#第六章-Java并发容器和框架" class="headerlink" title="第六章 Java并发容器和框架"></a>第六章 Java并发容器和框架</h1><h2 id="ConcurrentHashMap"><a href="#ConcurrentHashMap" class="headerlink" title="ConcurrentHashMap"></a>ConcurrentHashMap</h2><h3 id="为什么要使用ConcurrentHashMap"><a href="#为什么要使用ConcurrentHashMap" class="headerlink" title="为什么要使用ConcurrentHashMap?"></a>为什么要使用ConcurrentHashMap?</h3><ol>
<li><p>HashMap是线程不安全的</p>
<p> 多线程的情况下，使用HashMap进行put操作时会引起死循环</p>
</li>
</ol>
<hr>
<p><strong>未完待续。。。</strong></p>

    </div>

    
    
    

    <footer class="post-footer">
          

<div class="post-copyright">
<ul>
  <li class="post-copyright-author">
      <strong>本文作者： </strong>yorn
  </li>
  <li class="post-copyright-link">
      <strong>本文链接：</strong>
      <a href="http://wang-chen1119.gitee.io/myblog/2022/10/29/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/" title="Java并发编程的艺术读书笔记">http://wang-chen1119.gitee.io/myblog/2022/10/29/并发编程/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" rel="noopener" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>

          <div class="post-tags">
              <a href="/myblog/tags/%E5%B9%B6%E5%8F%91/" rel="tag"><i class="fa fa-tag"></i> 并发</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/myblog/2022/10/29/%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB/" rel="prev" title="事务隔离级别">
                  <i class="fa fa-chevron-left"></i> 事务隔离级别
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/myblog/2022/10/29/volatile%E5%85%B3%E9%94%AE%E5%AD%97/" rel="next" title="volatile关键字">
                  volatile关键字 <i class="fa fa-chevron-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">yorn</span>
</div>

    </div>
  </footer>

  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
<script src="/myblog/js/comments.js"></script><script src="/myblog/js/utils.js"></script><script src="/myblog/js/motion.js"></script><script src="/myblog/js/next-boot.js"></script><script src="/myblog/js/bookmark.js"></script>

  





  





<script src="/myblog/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>
